package com.scs.application.modules.wm.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.consts.SerialKeys;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.flow.FlowContext;
import com.scs.application.core.pdf.PdfExportUtils;
import com.scs.application.core.pdf.entity.PdfExportParams;
import com.scs.application.core.pdf.enums.PdfPageDirection;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.*;
import com.scs.application.modules.base.dto.ReagentTeamDTO;
import com.scs.application.modules.base.entity.*;
import com.scs.application.modules.base.mapper.MatrMapper;
import com.scs.application.modules.base.mapper.MfgMapper;
import com.scs.application.modules.base.mapper.ReagentTeamMapper;
import com.scs.application.modules.base.service.*;
import com.scs.application.modules.base.util.CommonService;
import com.scs.application.modules.base.util.MatrPassUtil;
import com.scs.application.modules.cfg.utils.ParameterUtils;
import com.scs.application.modules.dept.entity.ApplyAuto;
import com.scs.application.modules.dept.entity.DemandItem;
import com.scs.application.modules.dept.entity.DeptReturn;
import com.scs.application.modules.dept.entity.DeptReturnItem;
import com.scs.application.modules.dept.mapper.ApplyAutoMapper;
import com.scs.application.modules.dept.service.DemandItemService;
import com.scs.application.modules.dept.service.DeptReturnItemService;
import com.scs.application.modules.purchase.entity.Order;
import com.scs.application.modules.purchase.entity.OrderItem;
import com.scs.application.modules.purchase.enums.PoType;
import com.scs.application.modules.purchase.enums.PurchaseType;
import com.scs.application.modules.purchase.service.OrderItemService;
import com.scs.application.modules.purchase.service.OrderService;
import com.scs.application.modules.sys.model.RestResult;
import com.scs.application.modules.thirdparty.service.MscmService;
import com.scs.application.modules.wm.dto.*;
import com.scs.application.modules.wm.entity.*;
import com.scs.application.modules.wm.enums.WorkOrderType;
import com.scs.application.modules.wm.mapper.DistMapper;
import com.scs.application.modules.wm.mapper.InOrderItemMapper;
import com.scs.application.modules.wm.mapper.InOrderMapper;
import com.scs.application.modules.wm.mapper.WorkOrderItemMapper;
import com.scs.application.modules.wm.service.*;
import com.scs.application.modules.wm.utils.StockCommonService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 入库单 服务实现类
 * </p>
 */
@Slf4j
@Service
public class InOrderServiceImpl extends BaseServiceImpl<InOrderMapper, WorkOrder> implements InOrderService {
    @Autowired
    private InOrderItemService inOrderItemService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private WorkOrderItemService workOrderItemService;

    @Resource
    private InOrderItemMapper inOrderItemMapper;

    @Autowired
    private OrderBarcodeService orderBarcodeService;

    @Autowired
    private MscmService mscmService;

    @Autowired
    private WorkOrderService workOrderService;

    @Autowired
    private DeptReturnItemService deptReturnItemService;

    @Autowired
    private SupplierService supplierService;

    @Autowired
    private LocationLimitMatrService locationLimitMatrService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private DeptService deptService;

    @Autowired
    private DemandItemService demandItemService;

    @Autowired
    private LocationService locationService;

    @Resource
    private OrderItemService orderItemService;

    @Resource
    private MatrMapper matrMapper;

    @Resource
    private ApplyAutoMapper applyAutoMapper;

    @Autowired
    private MatrPassUtil matrPassUtil;

    @Autowired
    private PackTempletService packTempletService;

    @Resource
    private ReagentTeamMapper reagentTeamMapper;

    @Resource
    private DistMapper distMapper;
    @Resource
    private MatrUnitService matrUnitService;
    @Autowired
    @Lazy
    private ReagentTeamService reagentTeamService;
    @Autowired
    private MfgMapper mfgMapper;


    /**
     * 根据送货单号转换入库单
     *
     * @param asnKey
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized Map createWorkOrderByDelivery(String asnKey, String warehouseId, String deliveryman, String busUser, double arrivalTemperature, String reagentTeamId,String busType) {
        WorkOrder existWorkOrder = this.getOne(Wrappers.<WorkOrder>query().eq("asn_key", asnKey));
        if (existWorkOrder != null) {
            if (existWorkOrder.getFlowStatus().equals(GlobalConsts.FLOW_END_VALUE)) {
                throw new BusinessException("送货单%s已经入库过账,不能重复入库", asnKey);
            } else {
                List<String> orderIds = Lists.newArrayListWithCapacity(1);
                orderIds.add(existWorkOrder.getId());
                this.removeCascadeByIds(orderIds);
            }
        }
        HashMap<String, Object> map = Maps.newHashMap();
        DeliveryDTO deliveryDTO = mscmService.getDelivery(asnKey);
        if (deliveryDTO == null) {
            return map;
        }

        Order order = null;
        Warehouse warehouse = null;
        // scp手动采购订单
        if (GlobalConsts.PO_FROM_TYPE_SCP.equals(deliveryDTO.getFromType())) {
            BusinessException.throwErrorIf(StringUtils.isBlank(deliveryDTO.getWarehouseCode()), "收货仓库代码不存在，请联系供应商平台运营人员");
            warehouse = warehouseService.getOne(Wrappers.<Warehouse>query().eq("code",deliveryDTO.getWarehouseCode() ), false);
        } else {
            warehouse = warehouseService.getById(warehouseId);
            order = orderService.getById(deliveryDTO.getSourceKey());
            if (order == null ) {
                throw new BusinessException("未查询到SPD系统相关采购订单，发货单:%s，采购单:%s", asnKey, deliveryDTO.getPoCode());
            }

            if (order.getFlagClosed()) {
                throw new BusinessException("相关采购订单已关闭，无法入库，采购单号:%s", deliveryDTO.getPoCode());
            }

            //        采购订单收货仓库
            warehouseId = order.getWarehouseId();

            if (StringUtils.isNotEmpty(reagentTeamId)) {
                order.setReagentTeamId(reagentTeamId);
            }
        }

//        if (!deliveryDTO.getStatus().equals(DeliveryStatus.SEND.getStatus())) { //状态 : 0：制单；1：已发货；2：已收货
//            throw new BusinessException(String.format("送货单%s状态不正确，不是已发货状态，请确认" , asnKey));
//        }

        if (warehouse == null) {
            throw new BusinessException("入库仓库没有找到");
        }
        if (!warehouse.getFlagCenter()) {
            throw new BusinessException("入库仓库只能是中心仓库");
        }

        deliveryDTO.setArrivalTemperature(arrivalTemperature);

        WorkOrder workOrder = convertWorkOrder(deliveryDTO, warehouse.getId(), warehouse.getName(), deliveryman, busUser, order,busType);
        map.put("workOrder", workOrder);
        List<WorkOrderItem> workOrderItemList = inOrderItemService.list(new QueryWrapper<WorkOrderItem>()
                .eq("work_order_id", workOrder.getId()));
        if (ObjectUtil.length(deliveryDTO.getItems()) != ObjectUtil.length(workOrderItemList)) {
            throw new BusinessException("入库明细与发货明细不一致，请联系运营人员检查");
        }
        //是否禁用耗材校验-采购订单入库
        matrPassUtil.ckeckMatrPass("warehousing", workOrderItemList.stream().map(WorkOrderItem::getMatrId).collect(Collectors.toList()));
        map.put("items", workOrderItemList);
        return map;
    }

    private void fillEntity(WorkOrder entity) {
        if (StringUtils.isNotBlank(entity.getReagentTeamId())) {
            ReagentTeam reagentTeam =reagentTeamService.getById(entity.getReagentTeamId());
            if (reagentTeam != null) {
                entity.setReagentTeamName(reagentTeam.getName());
            }
        }
    }

    /**
     * 转换成workOrder
     *
     * @param deliveryDTO
     * @return
     */
    private WorkOrder convertWorkOrder(DeliveryDTO deliveryDTO, String warehouseId, String warehouseName, String deliveryman, String busUser, Order order,String busType) {
        if (deliveryDTO == null) {
            return null;
        }
        WorkOrder workOrder = new WorkOrder();
        Supplier supplier = supplierService.getSupplierByMscmCode(deliveryDTO.getSupplierId());
        workOrder.setAsnKey(deliveryDTO.getCode())
                .setRefKey(deliveryDTO.getPoCode())
                .setSupplierId(supplier == null ? null : supplier.getId())
                .setSupplierName(deliveryDTO.getSupplierName())
                .setAmount(deliveryDTO.getDeliveryAmount())
                .setFlagConsignment(deliveryDTO.getIsConsignment() == 1)
                .setFlagOmoc(deliveryDTO.getIsOneThingOneYard() == 1)
                .setBusType(WorkOrderType.IN_ASN)
                .setBusDate(Calendar.getInstance().getTime())
                .setDirection(GlobalConsts.ORDER_DIRECTION_IN)
                .setBusUser(busUser == null ? UserUtils.currentUser().getName() : busUser)
                .setDeliveryman(deliveryman)
                .setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.IN_ORDER_BUS_KEY))
                .setWarehouseId(warehouseId)
                .setWarehouseName(warehouseName).setDeliverTemperature(UtilNum.getDouble(deliveryDTO.getTemperature()))
                .setArrivalTemperature(UtilNum.getDouble(deliveryDTO.getArrivalTemperature()))
        ;
        workOrder.setId(IdWorker.getIdStr());

        if (WorkOrderType.IN_PACKAGE.equals(busType)) {
            workOrder.setBusType(WorkOrderType.IN_PACKAGE);
        }

        if (GlobalConsts.PO_FROM_TYPE_SCP.equals(deliveryDTO.getFromType())) { // 供应商平台手动订单

        } else {
            workOrder
                    .setRefId(order.getId()).setPurchaseOrderType(order.getPurchaseType())
                    .setPurchaseOrderId(order.getId())
                    .setReagentTeamId(order.getReagentTeamId())
                    .setRemark(order.getRemark())
                    .setDeptId(order.getDeptIdDemand())
                    .setDeptName(order.getDeptNameDemand())
                    .setReagentTeamId(order.getReagentTeamId())
            ;
        }

        if (order != null && GlobalConsts.PO_PACKAGE.equals(order.getPurchaseType())) {
            workOrder.setBusType(WorkOrderType.IN_PACKAGE);
        }

        List<WorkOrderItem> workOrderItemListAdd = new ArrayList<>();
        if (deliveryDTO.getItems() != null && deliveryDTO.getItems().size() > 0) {
            workOrder.setCountDtl(deliveryDTO.getItems().size());
            workOrderItemListAdd = inOrderItemService.saveOrderItemByDelivery(deliveryDTO.getItems(), workOrder.getId(), warehouseId, false,deliveryDTO);
            log.info("送货单入库完成，共生成{}条明细单", deliveryDTO.getItems().size());
        }
        workOrder.setAmount(0d);
        workOrder.setFlowStatus(GlobalConsts.FLOW_START_VALUE);

        if (!workOrderItemListAdd.isEmpty()) {
            workOrder.setAmount(UtilNum.getDouble(workOrderItemListAdd.stream().mapToDouble(WorkOrderItem::getAmount).sum()));
        }
        super.save(workOrder);
        fillEntity(workOrder);
        return workOrder;
    }

    /**
     * 根据出库单转换入库单
     *
     * @param outWorkOrder
     * @param transfer
     * @return
     */
    @Override
    public WorkOrder createWorkOrderByOut(WorkOrder outWorkOrder, Transfer transfer) {

        if (outWorkOrder == null || transfer == null) {
            throw new BusinessException("不正确的调拨单");
        }
        List<WorkOrderItem> workOrderItemList = workOrderItemService.list(new QueryWrapper<WorkOrderItem>().eq("work_order_id", outWorkOrder.getId()));
        if (workOrderItemList.size() == 0) {
            throw new BusinessException("出库单明细为空");
        }

        WorkOrder inWorkOrder = new WorkOrder();
        BeanUtils.copyProperties(outWorkOrder, inWorkOrder);
        inWorkOrder.setFlowStatus(GlobalConsts.FLOW_END_VALUE); //已审核
        inWorkOrder.setId(null);
        inWorkOrder.setRefId(transfer.getId()).setRefKey(transfer.getBusKey()).setRefTable("wm_transfer")
                .setBusType(WorkOrderType.IN_SHIFT)
                .setDirection(GlobalConsts.ORDER_DIRECTION_IN)
                .setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.IN_ORDER_BUS_KEY))
                .setWarehouseId(transfer.getToWarehouseId())
                .setWarehouseName(transfer.getToWarehouseName())
                .setFlowModifier(transfer.getFlowModifier())
                .setFlowModified(transfer.getFlowModified())
        ;

        //将调拨类型作为出入库类型
        if (StringUtils.isNotBlank(transfer.getType()) && GlobalConsts.TransferType.TransferTypeAll.contains(transfer.getType())) {
            inWorkOrder.setBusType(transfer.getType());
        } else {
            //同物理仓库之间调拨
            if (transfer.getFromWarehouseId().equals(transfer.getToWarehouseId())) {
                inWorkOrder.setBusType(WorkOrderType.IN_SHIFT_OW);
            }
        }

        super.save(inWorkOrder);

        inOrderItemService.saveOrderItemByOutOrder(workOrderItemList, inWorkOrder.getId(), inWorkOrder.getWarehouseId(), transfer.getToLocationId());

        return inWorkOrder;
    }

    /**
     * 根据科室退库转换入库单
     *
     * @param deptReturn
     * @return
     */
    @Override
    public List<WorkOrder> createWorkOrderByDeptReturn(DeptReturn deptReturn) {

        if (deptReturn == null || deptReturn == null) {
            throw new BusinessException("不正确的退库单");
        }
        List<DeptReturnItem> deptReturnItemList = deptReturnItemService.list(new QueryWrapper<DeptReturnItem>().eq("dept_return_id", deptReturn.getId()));
        if (deptReturnItemList.size() == 0) {
            throw new BusinessException("退库单明细为空");
        }

        //根据库存里面的供应商分组，因为耗材供应商可能被修改
        List<String> stockIdList = deptReturnItemList.stream().map(DeptReturnItem::getStockId).collect(Collectors.toList());
        List<Stock> stockList = StockCommonService.listStockWithZero(Wrappers.<Stock>query().in("id", stockIdList), null);
        if (stockList == null) {
            throw new BusinessException("退库单明细所对应的库存在系统中不存在，转换出库单失败");
        }
        if (stockList.size() != deptReturnItemList.size()) {
            throw new BusinessException("退库单明细数量【%s】与库存记录库存数量【%s】不一致，转换出库单失败", deptReturnItemList.size(), stockList.size());
        }

        //分组去重，条件：供应商，耗材，寄售，一物一码
        List<Stock> stockGroupList = UtilJava8.stockGroup(stockList);
        ArrayList<WorkOrder> orders = Lists.newArrayList();
        stockGroupList.stream().forEach(stockGroup -> {
            WorkOrderKey orderKey = new WorkOrderKey(stockGroup.getSupplierId(), stockGroup.getSupplierName(), stockGroup.getFlagConsignment(), stockGroup.getFlagOmoc());

            //符合该分组的所有库存
            List<Stock> stockAddList = UtilJava8.stockFilter(stockList, stockGroup);
            WorkOrder order = convertWorkOrder(deptReturn, orderKey, UtilJava8.getWODeptReturnItems(stockAddList, deptReturnItemList));
            orders.add(order);
        });
        log.info("退库完成，共生成{}张入库单", orders.size());
        return orders;
    }

    private WorkOrder convertWorkOrder(DeptReturn deptReturn, WorkOrderKey workOrderKey, List<DeptReturnItem> deptReturnItemList) {
        WorkOrder workOrder = new WorkOrder();

        // 查找原始配送单类型
        List<Dist> dist = distMapper.getDistBySn(deptReturnItemList.get(0).getSn(), deptReturn.getDeptId());
        String distType = dist.get(0).getDistType();

        Double amount = UtilCommon.doubleFormat(deptReturnItemList.stream().mapToDouble(DeptReturnItem::getAmount).sum());
        workOrder.setAsnKey("")
                .setRefTable("dept_return")
                .setRefKey(deptReturn.getBusKey())
                .setSupplierId(workOrderKey.getSupplierId())
                .setSupplierName(deptReturnItemList.get(0).getSupplierName())
                .setAmount(amount)
                .setRefId(deptReturn.getId())
                .setPurchaseOrderId(null)
                .setFlagConsignment(workOrderKey.getFlagConsignment())
                .setFlagOmoc(workOrderKey.getFlagOmoc())
                .setBusType(WorkOrderType.IN_DEPT_RETURN)
                .setBusDate(Calendar.getInstance().getTime())
                .setDirection(GlobalConsts.ORDER_DIRECTION_IN)
                .setBusUser(UserUtils.currentUser().getName())
                .setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.IN_ORDER_BUS_KEY))
                .setWarehouseId(deptReturn.getWarehouseId())
                .setWarehouseName(deptReturn.getWarehouseName())
                .setDeptId(deptReturn.getDeptId())
                .setDeptName(deptReturn.getDeptName())
                .setPurchaseOrderType(distType)
                .setFlowModifier(deptReturn.getFlowModifier()).setFlowModified(deptReturn.getFlowModified())
        ;
        workOrder.setFlowStatus(GlobalConsts.FLOW_END_VALUE);//审核完成
        super.save(workOrder);
        List<WorkOrderItem> workOrderItems = new ArrayList<>();
        deptReturnItemList.forEach(item -> {
            Location location = locationLimitMatrService.getSuitLocation(deptReturn.getWarehouseId(), item.getMatrId(), item.getPackageUnit());
            WorkOrderItem workOrderItem = new WorkOrderItem();
            BeanUtils.copyProperties(item, workOrderItem);
            workOrderItem.setWorkOrderId(workOrder.getId())
                    .setLocationId(location.getId())
                    .setLocationName(location.getName())
                    .setId(null);
            workOrderItem.setRefBusItemId(item.getId());
            workOrderItems.add(workOrderItem);
        });
        workOrderItemService.saveOrUpdateBatch(workOrderItems);
        return workOrder;
    }

    @Override
    protected void beforeHandleFlowChange(FlowContext flowContext, WorkOrder entity) {
        super.beforeHandleFlowChange(flowContext, entity);
        String buttonKey = flowContext.getButtonKey();
        // 提交审核，不允许空明细提交
        if ("submit".equalsIgnoreCase(buttonKey)) {
//            Integer count = inOrderItemService.count(Wrappers.<WorkOrderItem>query().eq("work_order_id", flowContext.getBusId()));
            //采购仓库检查 采购入库时，如果是由请领需求转换的，那么采购入库的仓库应该是需求仓库或者采购仓库
            WorkOrder entityDb = this.getById(entity.getId());
            if (entityDb == null) {
                throw new BusinessException("入库失败，采购入库单已被删除，单号:%s", entity.getBusKey());
            }
            if (WorkOrderType.IN_ASN.equals(entityDb.getBusType()) && StringUtils.isNotBlank(entityDb.getPurchaseOrderId())) {
                Order orderDb = orderService.getById(entityDb.getPurchaseOrderId());
                if (orderDb == null) {
                    throw new BusinessException("入库失败，采购单已被删除，采购订单id:%s", entityDb.getPurchaseOrderId());
                }
//                String applyWarehouseId = null,applyWarehouseName=" ";
//                if ("dept_demand".equals(orderDb.getRefTable())) { //由需求计划转换过来的采购订单
//                    Demand demand = demandMapper.selectById(orderDb.getRefId());
//                    if (demand == null )throw new BusinessException("入库失败，采购单所属需求计划已被删除，需求计划单号id:%s",orderDb.getRefKey());
//                    applyWarehouseId = demand.getApplyWarehouseId();
//                    applyWarehouseName = "或者需求申请仓库["+demand.getApplyWarehouseName()+"]";
//                    if (!entityDb.getWarehouseId().equals(demand.getApplyWarehouseId())) { //入库仓库非需求计划的申请仓库
//
//                    }
//                }
//                if (!entityDb.getWarehouseId().equals(orderDb.getWarehouseId()) && !entityDb.getWarehouseId().equals(applyWarehouseId)){
//                    throw new BusinessException("入库仓库[%s]选择错误，请重新选择<br>入库仓库应该为该采购订单的采购仓库[%s]%s",entityDb.getWarehouseName(),orderDb.getWarehouseName(),applyWarehouseName);
//                }
            }

            List<WorkOrderItem> workOrderItems = inOrderItemService.list(Wrappers.<WorkOrderItem>query().eq("work_order_id", flowContext.getBusId()));
            if (workOrderItems == null || workOrderItems.isEmpty()) {
                throw new BusinessException("请添加明细后提交");
            } else {
                //流程节点耗材校验--入库
                matrPassUtil.ckeckMatrPass("warehousing", workOrderItems.stream().map(WorkOrderItem::getMatrId).collect(Collectors.toList()));
                workOrderItems.stream().filter(s -> "1".equals(s.getMatrType())).forEach(s -> {
                    List<WorkOrderItem> orderItems = inOrderItemService.list(Wrappers.<WorkOrderItem>query().eq("pack_item_id", s.getId()));
                    if (orderItems == null || orderItems.isEmpty()) {
                        throw new BusinessException("很抱歉！存在没有耗材的跟台包，请删除空包重新选择跟台包后提交");
                    }
                    orderItems.forEach(workOrderItem -> {
                        if (workOrderItem.getPackageQty() <= 0) {
                            throw new BusinessException("很抱歉！耗材%s包装数量不能小于等于零，请检查包装数量", workOrderItem.getMatrName());
                        }
                    });
                });
                int max = Integer.parseInt(ParameterUtils.getSystemInPackageMax());
                WorkOrder workOrder = this.getById(entity.getId());
                workOrderItems.forEach(s -> {
                            if (!workOrder.getFlagOmoc() && s.getPackageQty() > max) {
                                throw new BusinessException("耗材%s品规%s包装数量超出限制%s，请更换包装单位", s.getMatrName(), s.getMatrSpec(), max);
                            }
                        }
                );

                checkMatrPass(workOrderItems.stream().map(WorkOrderItem::getMatrId).collect(Collectors.toList()));//校验耗材是否禁用
            }
//            if (!WorkOrderItemChange.isEmpty()) {
//                for (WorkOrderItem workOrderItem : WorkOrderItemChange) {
//                    Matr matrNew = matrMapper.selectById(workOrderItem.getMatrId());
//                    AdjustStockDTO adjustStockDTO = new AdjustStockDTO();
//                    BeanUtils.copyProperties(workOrderItem,adjustStockDTO);
//                    adjustStockDTO.setSupplierId(entity.getSupplierId()).setFlagOmoc(entity.getFlagOmoc())
//                            .setSupplierName(entity.getSupplierName());
//                    CommonService.priceChange(matrNew, adjustStockDTO, "MANUAL-IN-ORDER", "入库后价格与耗材价格不一致,自动调价,影响入库单号"+entity.getBusKey(),
//                            true,false, GlobalConsts.adjustTypeManual);
//                }
//            }
        } else if (StringUtils.equalsAnyIgnoreCase(buttonKey, "pass", "passone")) {
            List<WorkOrderItem> workOrderItems = inOrderItemService.list(Wrappers.<WorkOrderItem>query().eq("work_order_id", entity.getId()));
            if (CollectionUtils.isNotEmpty(workOrderItems)) {
                checkMatrPass(workOrderItems.stream().map(WorkOrderItem::getMatrId).collect(Collectors.toList()));//校验耗材是否禁用
            }
            //效期校验
            Date date = new Date();
            if (workOrderItems.stream().anyMatch(workOrderItem -> DateUtils.compareDate(workOrderItem.getExpDate(), date))) {
                throw new BusinessException("明细存在已过期耗材，请检查！");
            }
        }
    }

    private void checkMatrPass(List<String> idList) {
        try {
            List<Matr> matrList = matrMapper.selectList(Wrappers.<Matr>query().in("id", idList).eq("flag_disabled", 1));
            if (CollectionUtils.isNotEmpty(matrList)) {
                StringBuffer msg = new StringBuffer();
                matrList.stream().forEach(matr -> msg.append("品名：").append(matr.getName()).append("  品规：").append(matr.getSpec()));
                throw new BusinessException("耗材 " + msg.toString() + " 已经被禁用，请联系管理员！");
            }
        } catch (Exception e) {
            logger.info(e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    private void updatePurchaseOrder(WorkOrder workOrder) {
        if (StringUtils.isBlank(workOrder.getPurchaseOrderId())) {
            return;
        }
        //更新采购订单状态
        List<WorkOrder> workOrders = workOrderService.list(Wrappers.<WorkOrder>query()
                .eq("purchase_order_id", workOrder.getPurchaseOrderId()));
        double amount = UtilCommon.doubleFormat(workOrders.stream().filter(o -> o.getAmount() != null).mapToDouble(o -> o.getAmount()).sum());
        Order order = orderService.getById(workOrder.getPurchaseOrderId());
        Double orderAmount = order.getAmount();
        if (amount < orderAmount) {
            order.setStatusIn(GlobalConsts.OrderStatusIn.PART_IN);
        }
        if (amount == orderAmount) {
            order.setStatusIn(GlobalConsts.OrderStatusIn.ALL_IN);
        }
        order.setSyncStatus(GlobalConsts.OrderSyncStatus.DELIVERED);
        orderService.updateById(order);
        //更新采购明细入库数量,入库状态
        List<WorkOrderItem> inOrderItemList = workOrderItemService.list(Wrappers.<WorkOrderItem>query().eq("work_order_id", workOrder.getId()));
        List<OrderItem> orderItemList = orderItemService.list(Wrappers.<OrderItem>query().eq("order_Id", workOrder.getPurchaseOrderId()));
        if (!inOrderItemList.isEmpty()) {
            //根据采购明细Id分组
            Map<String, List<WorkOrderItem>> map = inOrderItemList.stream().collect(Collectors.groupingBy(o -> workOrder.getBusType().equals(WorkOrderType.IN_ASN) ? o.getPoItemId() : o.getMatrId()));
            List<OrderItem> orderItems = Lists.newArrayListWithCapacity(map.size());
            for (String key : map.keySet()) {
                List<WorkOrderItem> items = map.get(key);
                Double inSkuQty = items.stream().mapToDouble(WorkOrderItem::getSkuQty).sum();
                Optional<OrderItem> optOrderItem;
                if (workOrder.getBusType().equals(WorkOrderType.IN_ASN)) { //供应商入库的，按poitemId来查
                    //查询采购订单明细
                    String poItemId = items.get(0).getPoItemId();
                    if (StringUtils.isBlank(poItemId)) {
                        continue;
                    }
                    optOrderItem = orderItemList.stream().filter(poItem -> poItemId.equals(poItem.getId())).findFirst();
                    if (!optOrderItem.isPresent()) {
                        throw new BusinessException("采购单明细ID为：%s明细不存在", items.get(0).getPoItemId());
                    }
                } else { //手动入库的，按耗材来查
                    //查询采购订单明细
                    String matrId = items.get(0).getMatrId();
                    optOrderItem = orderItemList.stream().filter(poItem -> matrId.equals(poItem.getMatrId())).findFirst();
                    if (!optOrderItem.isPresent()) { //不报错，直接跳过
                       continue;
                    }
                }
                OrderItem orderItem = optOrderItem.get();
                inSkuQty = orderItem.getInSkuQty() + inSkuQty;
                if (inSkuQty > 0 && inSkuQty < orderItem.getSkuQty()) {
                    //部分入库
                    orderItem.setStatusIn("1");
                } else if (Math.abs(inSkuQty - orderItem.getSkuQty()) < 1e-6) {
                    //全部入库
                    orderItem.setStatusIn("2");
                } else {
                    //未入库
                    orderItem.setStatusIn("0");
                }
                OrderItem item = new OrderItem();
                item.setInSkuQty(inSkuQty).setStatusIn(orderItem.getStatusIn()).setId(orderItem.getId());
                orderItems.add(item);
            }
            //更新采购明细入库状态入库数量
            if (!orderItems.isEmpty()) {
                orderItemService.updateBatchById(orderItems);
            }
        }
        //更新需求明细状态
        orderItemList.stream().forEach(orderItem -> {
            CommonService.updateApplyItemStatus(orderItem.getApplyItemId(), false, null);
        });
        //更新在途数量
        CommonService.updateApplyInfo(Collections.singletonList(workOrder.getPurchaseOrderId()), 1);

        //通知已入库
        if (ParameterUtils.isAllowInternet() && workOrder.getBusType().equals(WorkOrderType.IN_ASN)) {
            mscmService.notifyOrder(workOrder.getAsnKey());
        }
    }

    @Override
    protected void afterHandleFlowChange(FlowContext flowContext, WorkOrder entity) {
        super.afterHandleFlowChange(flowContext, entity);

        if (flowContext.isEndNode()) {
            // 将所有Item的lineId更新为workOrderItemId
            inOrderItemMapper.updateLineId(entity.getId());
            //审核通过后直接入库
//            workOrderService.post(entity.getId());
            workOrderService.postBatch(Collections.singletonList(entity.getId()));
            flowContext.setHandledMsg("流程操作完成，相应库存已增加");

            WorkOrder workOrder = super.getById(entity.getId());
            if (allowAutoChangeTransfer(workOrder)) { //判断是否可以自动转调拨
                workOrder.setAllowChangeTransfer(true);
                super.updateById(workOrder);
            }
            //更新采购订单状态
            updatePurchaseOrder(workOrder);
        } else {
            WorkOrder workOrder = super.getById(entity.getId());
            //更新需求明细状态
            List<OrderItem> orderItemList = orderItemService.list(Wrappers.<OrderItem>query().eq("order_Id", workOrder.getPurchaseOrderId()));
            orderItemList.stream().forEach(orderItem -> {
                CommonService.updateApplyItemStatus(orderItem.getApplyItemId(), false, null);
            });
        }

    }

    /**
     * 判断是否可以自动转成配送单
     *
     * @param workOrder
     * @return
     */
    @Override
    public boolean allowAutoChangeDist(WorkOrder workOrder) {
        if (StringUtils.isNotBlank(workOrder.getRefDistId()) && !"0".equals(workOrder.getRefDistId())) { //如已经有关联，直接返回false
            return false;
        }
        if (!ParameterUtils.isAutoChangeDist() || StringUtils.isBlank(workOrder.getPurchaseOrderId())) {
            return false;
        }

        Order order = orderService.getById(workOrder.getPurchaseOrderId());
        if (order == null || StringUtils.isBlank(order.getDeptIdDemand()) || StringUtils.isBlank(order.getWarehouseId())) {
            return false;
        }

        //判断是否自动生成配送单
        if (!workOrder.getFlagOmoc() && demandItemService.count(new QueryWrapper<DemandItem>().eq("order_id", order.getId())) > 0) {
            return true;//由需求产生
        }

        //由自动请领产生
        List<ApplyAuto> applyAutos = applyAutoMapper.simpleList(new QueryWrapper<ApplyAuto>().eq("ref_order_id", order.getId()));
        if (applyAutos != null && applyAutos.size() > 0) {
            return !workOrder.getFlagOmoc() && applyAutos.get(0).getRefType().indexOf("dept") > -1;
        }

        return false;
    }

    /**
     * 判断是否需要调价
     *
     * @param workOrder
     * @return
     */
    @Override
    public boolean allowAutoAdjust(WorkOrder workOrder) {

        List<WorkOrderItem> inOrderItemList = workOrderItemService.list(Wrappers.<WorkOrderItem>query().eq("work_order_id", workOrder.getId()).ne("matr_type","1"));

        List<String> matrIds = inOrderItemList.stream().map(s -> s.getMatrId()).collect(Collectors.toList());
        List<Matr> matrList = matrMapper.selectList(Wrappers.<Matr>query().in("id", matrIds));

        //价格变动的入库明细
        List<WorkOrderItem> WorkOrderItemChange = inOrderItemList.stream().filter(workOrderItem -> matrList.stream()
                .filter(matr -> matr.getId().equals(workOrderItem.getMatrId())
                        && matr.getSupplierId().equals(workOrder.getSupplierId())
                        && matr.getFlagOmoc().equals(workOrder.getFlagOmoc())
                        && !matr.getSkuPrice().equals(workOrderItem.getSkuPrice())).count() > 0)
                .collect(Collectors.toList());

        return !WorkOrderItemChange.isEmpty();
    }

    /**
     * 判断是否需要调价
     *
     * @param workOrder
     * @return
     */
    @Override
    public boolean workOderItemAdjust(WorkOrder workOrder) {

        List<WorkOrderItem> inOrderItemList = workOrderItemService.list(Wrappers.<WorkOrderItem>query().eq("work_order_id", workOrder.getId()));

        List<String> matrIds = inOrderItemList.stream().map(s -> s.getMatrId()).collect(Collectors.toList());
        List<Matr> matrList = matrMapper.selectList(Wrappers.<Matr>query().in("id", matrIds));

        //价格变动的入库明细
        List<WorkOrderItem> WorkOrderItemChange = inOrderItemList.stream().filter(workOrderItem -> matrList.stream()
                .filter(matr -> matr.getId().equals(workOrderItem.getMatrId())
                        && matr.getSupplierId().equals(workOrder.getSupplierId())
                        && matr.getFlagOmoc().equals(workOrder.getFlagOmoc())
                        && !matr.getSkuPrice().equals(workOrderItem.getSkuPrice())).count() > 0)
                .collect(Collectors.toList());
        for (WorkOrderItem workOrderItem : WorkOrderItemChange) {
            Matr matr = matrMapper.selectById(workOrderItem.getMatrId());
            workOrderItem.setSkuPrice(matr.getSkuPrice());
            workOrderItem.setAmount(matr.getSkuPrice() * workOrderItem.getSkuQty());
            workOrderItem.setRemark("耗材价格变更,自动调价");
            workOrderItemService.updateCascadeById(workOrderItem);
        }
        workOrder.setRemark("[耗材价格变更,自动调价]" + UtilCommon.getStr(workOrder.getRemark(), ""));
        this.updateCascadeById(workOrder);
        baseMapper.calculateOrderPrice(workOrder.getId());

        return !WorkOrderItemChange.isEmpty();
    }

    /**
     * 判断是否可以自动转成调拨单
     *
     * @param workOrder
     * @return
     */
    @Override
    public boolean allowAutoChangeTransfer(WorkOrder workOrder) {
        if (StringUtils.isNotBlank(workOrder.getRefTransferId()) && !"0".equals(workOrder.getRefTransferId())) { //如已经有关联，直接返回false
            return false;
        }

        if (!ParameterUtils.isAutoChangeDist() || StringUtils.isBlank(workOrder.getPurchaseOrderId())) {
            return false;
        }

        Order order = orderService.getById(workOrder.getPurchaseOrderId());

        if (order == null || StringUtils.isBlank(order.getDeptIdDemand()) || StringUtils.isBlank(order.getWarehouseId())) {
            return false;
        }

        Dept dept = deptService.getById(order.getDeptIdDemand());
        if (dept.getWarehouseId() == null) {
            return false;
        }

        Warehouse warehouse = warehouseService.getById(workOrder.getWarehouseId());//入库仓库
        //入库转调拨, 采购订单需求科室 不等于 入库仓库对应科室,入库仓库等于中心库房  就进行转调拨
        return !dept.getWarehouseId().equals(warehouse.getId()) && warehouse.getFlagCenter();
    }

    @Override
    public boolean saveOrUpdate(WorkOrder workOrder) {
        if (workOrder.isNewRecord()) {
            workOrder.setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.IN_ORDER_BUS_KEY));
        }
        if (workOrder.getDirection() == null) {
            workOrder.setDirection(GlobalConsts.ORDER_DIRECTION_IN);
        }

        if (StringUtils.isBlank(workOrder.getBusType())) {
            throw new BusinessException("出入库业务类型为空！");
        }

        // 期初入库自动设置供应商信息
        if (workOrder.isNewRecord() && workOrder.getBusType().equals(WorkOrderType.IN_INIT)) {
            List<Supplier> supplierList = supplierService.list(Wrappers.<Supplier>query().eq("name", "期初供应商"));
            BusinessException.throwErrorIf(supplierList == null || supplierList.size() == 0 ,"未找到名称为【期初供应商】的供应商信息，请联系运营人员进行设置");
            BusinessException.throwErrorIf(supplierList.size() > 1 ,"名称为【期初供应商】的供应商找到多个，请联系运营人员进行检查");
            workOrder.setSupplierId(supplierList.get(0).getId()).setSupplierName(supplierList.get(0).getName());
        }

        if (StringUtils.isBlank(workOrder.getDeptId())) {
            workOrder.setDeptId(null);
        }

        //数据库中是Long类型，不能存空值
        if (StringUtils.isBlank(workOrder.getPurchaseOrderId())) {
            workOrder.setPurchaseOrderId(null);
        }
        if (StringUtils.isBlank(workOrder.getInvoiceGroupId())) {
            workOrder.setInvoiceGroupId(null);
        }
        if (StringUtils.isBlank(workOrder.getRefId())) {
            workOrder.setRefId(null);
        }

        if (WorkOrderType.IN_MANUAL.equals(workOrder.getBusType())
                && PurchaseType.REAGENT.getKey().equals(workOrder.getPurchaseOrderType())
                && StringUtils.isEmpty(workOrder.getRefId())) {
            // 手工入库，采购单号为空，如果是试剂类型，根据试剂组自动带出科室
            if (StringUtils.isNotEmpty(workOrder.getReagentTeamId())) {
                ReagentTeamDTO reagentTeam = reagentTeamMapper.getDeptById(workOrder.getReagentTeamId());
                if (reagentTeam != null) {
                    workOrder.setDeptId(reagentTeam.getDeptId()).setDeptName(reagentTeam.getDeptName());
                }
            }
        }

        return super.saveOrUpdate(workOrder);
    }

    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        inOrderItemService.remove(new QueryWrapper<WorkOrderItem>().in("work_order_id", idList));
        orderBarcodeService.remove(new QueryWrapper<OrderBarcode>().in("work_order_id", idList));
        return this.removeByIds(idList);
    }

    @Override
    public void preview(String workOrderId, HttpServletResponse response) {
        response.setContentType(MediaType.APPLICATION_PDF_VALUE);

        WorkOrder workOrder = super.getById(workOrderId);
        if (workOrder == null) {
            return;
        }

        PdfExportParams exportParams = new PdfExportParams();
        exportParams.setTitle(String.format("%s入库单", workOrder.getWarehouseName()));
        exportParams.setPerRowsOfGrid(10);
        exportParams.setPageDirection(PdfPageDirection.TRANSVERSE);
        exportParams.setWatermark("本公司");
        exportParams.setQrcodeText(workOrder.getBusKey());
        exportParams.setBarcodeText(workOrder.getBusKey());


        exportParams.addHeaderItem("供应商", workOrder.getSupplierName(), 12)
                .addHeaderItem("送货单号", workOrder.getAsnKey(), 12)
                .addHeaderItem("入库日期", workOrder.getBusDate(), 12)
                .addHeaderItem("入库单号", workOrder.getBusKey(), 12);

        exportParams.addGridColumn("rowIndex", "序号", 3)
                .addGridColumn("matrName", "材料名称", 9)
                .addGridColumn("matrSpec", "规格型号", 3)
                .addGridColumn("skuUnit", "单位", 2)
                .addGridColumn("skuQty", "数量", 2)
                .addGridColumn("skuPrice", "单价", 2)
                .addGridColumn("amount", "金额", 3);

        List<WorkOrderItem> workOrderItemList = inOrderItemService.list(new QueryWrapper<WorkOrderItem>().eq("work_order_id", workOrderId));
        double wholeNum = 0; //产品总数
        if (workOrderItemList.size() > 0) {
            exportParams.setGridData(workOrderItemList);
            wholeNum = workOrderItemList.stream().mapToDouble(WorkOrderItem::getSkuQty).sum();
        }

        exportParams.addFooterItem("制单人", workOrder.getBusUser(), 8)
                .addFooterItem("经办人", workOrder.getFlowModifier(), 8)
                .addFooterItem("总数", wholeNum, 8);

        try {
            PdfExportUtils.export(response.getOutputStream(), exportParams);
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    public RestResult isExist(String asnKey) {
        WorkOrder existWorkOrder = this.getOne(Wrappers.<WorkOrder>query().eq("asn_key", asnKey));
        if (existWorkOrder != null) {
            if (existWorkOrder.getFlowStatus().equals(GlobalConsts.FLOW_END_VALUE)) {
                throw new BusinessException(String.format("送货单%s已经入库过账,不能重复入库", asnKey));
            }
        }
        return null;
    }

    @Override
    public synchronized WorkOrder createWorkOrderByQrCode(String warehouseId, String qrCode, String inOrderId, String deliveryman, String busUser) {
        String jsonQrCode = "";
        try {
            jsonQrCode = UtilJavax.unzip(qrCode);
            if (StringUtils.isNotBlank(inOrderId) && !"0".equals(inOrderId)) { //表示是子单
                List<DeliveryDTO.DeliveryItemDTO> deliveryItemDTOS = JSONObject.parseArray(jsonQrCode, DeliveryDTO.DeliveryItemDTO.class);
                if (deliveryItemDTOS == null || deliveryItemDTOS.size() == 0) {
                    throw new BusinessException("二维码信息有误,主单已扫描，请扫描子单信息");
                }
                deliveryItemDTOS.forEach(item -> {
                    OrderItem orderItem = orderItemService.getById(item.getSourceKey());
                    if (orderItem != null) {
                        Matr matr = matrMapper.selectById(orderItem.getMatrId());
                        item.setMaterialName(orderItem.getMatrName())
                                .setMaterialCode(matr == null ? "" : matr.getMscmCode())
                                .setCertificateNo(matr.getCertificateNo())
                                .setMaterialSpec(orderItem.getMatrSpec())
                                .setOrderUnit(orderItem.getPackageUnit())
                                .setOrderQty(orderItem.getSkuQty() / orderItem.getPackageQty())
                                .setSubtotalAmount(orderItem.getSkuPrice() * item.getQty())
                                .setPrice(orderItem.getSkuPrice())
                                .setUnit(orderItem.getSkuUnit())
                                .setManufacturerName(matr.getMfgName());
                    }
                });
                inOrderItemService.saveOrderItemByDelivery(deliveryItemDTOS, inOrderId, warehouseId, true, null);
                workOrderService.calculateOrderPrice(inOrderId);
                WorkOrder workOrder = workOrderService.getById(inOrderId);
                return workOrder;
            } else { //主单
                DeliveryDTO delivery = JSONObject.parseObject(jsonQrCode, DeliveryDTO.class);
                if (delivery == null) {
                    throw new BusinessException("二维码信息有误,请先扫描主单");
                }
                WorkOrder existWorkOrder = this.getOne(Wrappers.<WorkOrder>query().eq("asn_key", delivery.getCode()));
                if (existWorkOrder != null) {
                    if (existWorkOrder.getFlowStatus().equals(GlobalConsts.FLOW_END_VALUE)) {
                        throw new BusinessException(String.format("送货单%s已经入库过账,不能重复入库", delivery.getCode()));
                    } else {
                        List<String> orderIds = Lists.newArrayListWithCapacity(1);
                        orderIds.add(existWorkOrder.getId());
                        this.removeCascadeByIds(orderIds);
                    }
                }
                Order order = orderService.getOne(Wrappers.<Order>query().eq("id", delivery.getSourceKey()));
                if (order == null) {
                    throw new BusinessException("未查询到SPD系统相关采购订单，发货单:%s，采购单Id:%s", delivery.getCode(), delivery.getSourceKey());
                }
                String warehouseName = "";
                if (!StringUtils.isBlank(warehouseId)) {
                    Warehouse warehouse = warehouseService.getById(warehouseId);
                    warehouseName = warehouse == null ? "" : warehouse.getName();
                }
                delivery.setPoCode(order.getBusKey())
                        .setSupplierName(order.getSupplierName())
                        .setDeliveryAmount(0d) //先设为0，再扫子单后再统计
                        .setIsConsignment(PoType.CONSIGNMENT.getValue().equals(order.getPoType()) ? 1 : 0)
                        .setIsOneThingOneYard(order.getFlagOmoc() ? 1 : 0);

                Supplier supplier = supplierService.getOne(Wrappers.<Supplier>query().eq("id", order.getSupplierId()));
                delivery.setSupplierId(supplier != null ? supplier.getMscmCode() : order.getSupplierId());
                WorkOrder workOrder = convertWorkOrder(delivery, warehouseId, warehouseName, deliveryman, busUser, order, null);
                return workOrder;
            }
        } catch (Exception ex) {
            if (StringUtils.isNotBlank(inOrderId) && !"0".equals(inOrderId)) { //表示是子单
                logger.error(ex.getMessage());
                throw new BusinessException("二维码信息有误,主单已扫描，请扫描子单信息");
            } else {
                throw new BusinessException("二维码信息有误,请先扫描主单");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatchForInOrder(List<WorkOrderItemDTO> entityList) {
        WorkOrderItemDTO workOrderItem = entityList.get(0);
        WorkOrder workOrder = this.getById(workOrderItem.getWorkOrderId());

        // 查询现有入库单明细
        WorkOrderItemMapper itemMapper = (WorkOrderItemMapper) workOrderItemService.getBaseMapper();
        WorkOrderItemDTO query = new WorkOrderItemDTO();
        query.setWorkOrderId(workOrderItem.getWorkOrderId());
        List<WorkOrderItemDTO> items = itemMapper.getList(query);
        if (CollectionUtils.isNotEmpty(entityList)) {
            // 不同耗材类型不允许添加
            WorkOrderItemDTO first = entityList.get(0);
            if (entityList.stream().anyMatch(itemDto -> !first.getBaseType().equals(itemDto.getBaseType()))) {
                throw new BusinessException("不允许同时选择多种类型的耗材");
            }
        }

        // 初始化耗材类型
        String purchaseOrderType = workOrder.getPurchaseOrderType();
        if (CollectionUtils.isEmpty(items)) {
            //更新入库单耗材类型
            purchaseOrderType = PurchaseType.MATR.getKey();
            if (entityList.stream().anyMatch(itemDto -> PurchaseType.REAGENT.getKey().equals(itemDto.getBaseType()))) {
                purchaseOrderType = PurchaseType.REAGENT.getKey();
            }
        } else {
            // 校验耗材类型
            String type = purchaseOrderType;
            if (entityList.stream().anyMatch(itemDto -> !type.equals(itemDto.getBaseType()))) {
                throw new BusinessException("选择的耗材类型与入库单的耗材类型不一致，不允许入库");
            }
        }

//        仓库默认库位
        Location defaultLocation = locationService.getDefaultLocation(workOrder.getWarehouseId());

        List<WorkOrderItemDTO> workOrderItemDTOS = entityList.stream().filter(item ->
                workOrder.getSupplierId().equals(item.getSupplierId())
                        && workOrder.getFlagOmoc().equals(item.getFlagOmoc())
                        && workOrder.getFlagConsignment().equals(item.getFlagConsignment()))
                .collect(Collectors.toList());
        if (workOrder.getBusType().equals(WorkOrderType.IN_INIT)) {
            workOrderItemDTOS = entityList.stream().filter(item ->
                    workOrder.getFlagOmoc().equals(item.getFlagOmoc())
                            && workOrder.getFlagConsignment().equals(item.getFlagConsignment()))
                    .collect(Collectors.toList());
        }


        List<WorkOrderItem> saveItem = new ArrayList<>();
        //是否禁用耗材校验-入库保存选择耗材明细
        matrPassUtil.ckeckMatrPass("warehousing", workOrderItemDTOS.stream().map(WorkOrderItemDTO::getMatrId).collect(Collectors.toList()));

        List<String> matrIdList = workOrderItemDTOS.stream().map(WorkOrderItemDTO::getMatrId).collect(Collectors.toList());
        Map<String, List<MatrUnit>> matrUnitMap = matrUnitService.list(
                Wrappers.<MatrUnit>query()
                        .in("matr_id", matrIdList)
                        .eq("flag_purchase", 1)
                        .orderByDesc("rate")
        ).stream().collect(Collectors.groupingBy(MatrUnit::getMatrId));
        Date nowDate  = DateUtils.nowDate("yyyy-MM-dd");
        for (WorkOrderItemDTO itemDTO : workOrderItemDTOS) {
            WorkOrderItem itemNew = new WorkOrderItem();
            BeanUtils.copyProperties(itemDTO, itemNew);
            itemNew.setLocationId(defaultLocation.getId()).setLocationName(defaultLocation.getName())
                    .setPackageUnit(itemNew.getSkuUnit()).setPackageQty(1D).setSkuQty(1D).setId(null);

            if (StringUtils.isBlank(itemDTO.getLot())) {
                itemNew.setLot("无");
            }
            if (itemDTO.getMfgDate() == null) {
                itemNew.setMfgDate(nowDate);
            }
            if (itemDTO.getExpDate() == null) {
                itemNew.setExpDate(DateUtils.addMonth(nowDate, 6));
            }

            if (matrUnitMap != null && matrUnitMap.get(itemNew.getMatrId()) != null) {
                itemNew.setPackageUnit(matrUnitMap.get(itemNew.getMatrId()).get(0).getUnit());
                itemNew.setSkuQty(matrUnitMap.get(itemNew.getMatrId()).get(0).getRate());
                itemNew.setPackageRate(matrUnitMap.get(itemNew.getMatrId()).get(0).getRate());
            }
            BusinessException.throwValidFailIf(itemNew.getSkuPrice() == null, "商品[%s],规格[%s]缺少单品价格,请检查",itemNew.getMatrName(),itemNew.getMatrSpec());
            itemNew.setAmount(itemNew.getSkuQty() * itemNew.getSkuPrice());

            saveItem.add(itemNew);
        }
        workOrderItemService.saveBatch(saveItem);
        updateAmount(workOrder.getId(), purchaseOrderType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult createWorkOrderByOrthScan(OrthWiDTO orthWiDTO) {
        Optional.ofNullable(orthWiDTO).orElseThrow(() -> new BusinessException("主单信息不存在,请检查！"));
        if (CollectionUtils.isEmpty(orthWiDTO.getItems())) {
            throw new BusinessException("包内明细 信息不存在,请检查！");
        }
        double sumOrthWiItemQty = orthWiDTO.getItems().stream().mapToDouble(OrthWiItemDTO::getQty).sum();
        if (sumOrthWiItemQty > orthWiDTO.getTotalQty()) {
            throw new BusinessException("传入数量%s 大于入库总数：%s,请检查！", sumOrthWiItemQty, orthWiDTO.getTotalQty());
        }
        WorkOrder workOrder = this.getOne(Wrappers.<WorkOrder>query().eq("asn_key", orthWiDTO.getOipWiSn()));

        Warehouse warehouse = warehouseService.list(new QueryWrapper<Warehouse>().eq("flag_center", "1")).stream().findFirst().get();
        Location location = locationService.list(new QueryWrapper<Location>().eq("warehouse_id", warehouse.getId())).stream().findFirst().get();

        Optional.ofNullable(workOrder).orElseGet(() -> convertWorkOrderByOrthScan(orthWiDTO, warehouse, location, sumOrthWiItemQty));

        Optional.ofNullable(workOrder).ifPresent(item -> inOrderItemService.saveOrderItemByOrthScan(orthWiDTO, item, warehouse.getId(), location, null, sumOrthWiItemQty));

        return RestResult.ok("保存成功");
    }

    private WorkOrder convertWorkOrderByOrthScan(OrthWiDTO orthWiDTO, Warehouse warehouse, Location location, double sumOrthWiItemQty) {

        WorkOrder workOrder = new WorkOrder();
        PackTemplet packTemplet = packTempletService.getById(orthWiDTO.getPackageCode());

        Optional.ofNullable(packTemplet).orElseThrow(() -> new BusinessException("未查询到跟台包信息，请检查骨科跟台包编码：%s", orthWiDTO.getPackageCode()));
        Optional.ofNullable(packTemplet.getSupplierId()).orElseThrow(() -> new BusinessException("该跟台包未维护供应商信息，请检查！"));
        workOrder.setAsnKey(orthWiDTO.getOipWiSn())
                .setSupplierId(packTemplet.getSupplierId())
                .setSupplierName(supplierService.getById(packTemplet.getSupplierId()).getName())
                .setAmount(packTemplet.getAmount())
                .setFlagConsignment(true)
                .setFlagOmoc(true)
                .setBusType(WorkOrderType.IN_SCANNER)
                .setBusDate(Calendar.getInstance().getTime())
                .setDirection(GlobalConsts.ORDER_DIRECTION_IN)
                .setBusUser(UserUtils.currentUser().getName())
                .setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.IN_ORDER_BUS_KEY))
                .setWarehouseId(warehouse.getId())
                .setWarehouseName(warehouse.getName());
        super.save(workOrder);

        WorkOrderItem workOrderItem = new WorkOrderItem();
        workOrderItem.setWorkOrderId(workOrder.getId())
                .setLocationId(location.getId())
                .setLocationName(location.getName())
                .setExpDate(new Date())
                .setMfgDate(new Date())
                .setLot(orthWiDTO.getBatch())
                .setMatrName(packTemplet.getName())
                .setPackId(packTemplet.getId())
                .setAmount(packTemplet.getAmount())
                .setMatrType("1")
                .setMatrId("-1")
                .setMatrSpec("")
                .setPackageUnit("")
                .setPackageQty(1.0)
                .setSkuPrice(packTemplet.getAmount())
                .setSkuQty(1.0)
                .setSkuUnit("包")
                .setPackageUnit("包");
        workOrderItemService.save(workOrderItem);

        inOrderItemService.saveOrderItemByOrthScan(orthWiDTO, workOrder, warehouse.getId(), location, workOrderItem.getId(), sumOrthWiItemQty);
        log.info("骨科扫描仪入库完成，共生成{}条明细单", orthWiDTO.getItems().size());

        return workOrder;
    }

    /**
     * 修改 WorkOrder表中包金额及单品价格
     *
     * @param workOrderId
     */
    private void updateAmount(String workOrderId, String purchaseOrderType) {
        Map<String, Object> workOrderMap = workOrderItemService.getMap(new QueryWrapper<WorkOrderItem>().select("sum(amount) as amount")
                .eq("work_order_id", workOrderId));
        workOrderService.update(Wrappers.<WorkOrder>update()
                .set("amount", workOrderMap.get("amount") == null ? 0 : workOrderMap.get("amount"))
                //.set("purchase_order_type", purchaseOrderType)
                .eq("id", workOrderId));
    }


    // 填充属性
    private void fillStockInfo(List<Stock> stockList) {
        // 仓库信息
        List<String> warehouseNameList = stockList.stream().map(Stock::getWarehouseName).distinct().collect(Collectors.toList());
        Map<String,Warehouse> warehouseByName = warehouseService.list(Wrappers.<Warehouse>query().in("name",warehouseNameList))
                .stream().collect(Collectors.toMap(Warehouse::getName, t -> t));
        if (warehouseByName.keySet().size() != warehouseNameList.size()) {
            warehouseNameList.stream().filter(find -> !warehouseByName.keySet().contains(find)).findFirst().ifPresent(find2 -> {
                BusinessException.throwValidFail("仓库[%s]未找到，请先创建",find2);
            });
        }


        // 供应商信息
        List<String> spNameList = stockList.stream().map(Stock::getSupplierName).distinct().collect(Collectors.toList());
        Map<String,Supplier> spByName = supplierService.list(Wrappers.<Supplier>query().in("name",spNameList))
                .stream().collect(Collectors.toMap(Supplier::getName, t -> t));
        if (spByName.keySet().size() != spNameList.size()) {
            spNameList.stream().filter(find -> !spByName.keySet().contains(find)).findFirst().ifPresent(find2 -> {
                BusinessException.throwValidFail("供应商[%s]未找到，请先创建",find2);
            });
        }

        // 商品信息  供应商名称	商品名称	商品规格 分组
        List<String> matrNameList = stockList.stream().map(Stock::getMatrName).distinct().collect(Collectors.toList());
        List<Matr> matrLIst = matrMapper.selectList(Wrappers.<Matr>query().in("name",matrNameList));
        Map<String,List<Matr>> matrBySpAndNameAndSpec =matrLIst
                .stream().collect(Collectors.groupingBy(t -> t.getSupplierName() + t.getName() + t.getSpec()));;

        // 厂商
        List<String> mfgNameList = stockList.stream().map(Stock::getMfgName).distinct().collect(Collectors.toList());
        Map<String,Mfg> mfgByName = mfgMapper.selectList(Wrappers.<Mfg>query().in("name",mfgNameList))
                .stream().collect(Collectors.toMap(Mfg::getName, t -> t));


        // 填充信息
        String matrFindKey ;
        Matr matrFind;

        List<String> matrIdList = matrLIst.stream().map(Matr::getId).collect(Collectors.toList());
        Map<String, List<MatrUnit>> matrUnitMapByMatrIdAndUnit = matrUnitService.list(
                Wrappers.<MatrUnit>query()
                        .in("matr_id", matrIdList)
                        .orderByDesc("rate")
        ).stream().collect(Collectors.groupingBy(t -> t.getMatrId() + t.getUnit()));
        String unitFindKey;
        int lineIndex = 0;
        Mfg mfgFind;
        for(Stock stock : stockList) {
            lineIndex++;
            stock.setWarehouseId(warehouseByName.get(stock.getWarehouseName()).getId());
            stock.setSupplierId(spByName.get(stock.getSupplierName()).getId());

            matrFindKey = stock.getSupplierName() + stock.getMatrName() +stock.getMatrSpec();
            if (!matrBySpAndNameAndSpec.containsKey(matrFindKey)) {
                BusinessException.throwValidFail("第%s行,商品未找到",lineIndex);
            }
            if (matrBySpAndNameAndSpec.get(matrFindKey).size() > 1) {
                BusinessException.throwValidFail("第%s行,商品找到多个",lineIndex);
            }
            matrFind = matrBySpAndNameAndSpec.get(matrFindKey).get(0);
            stock.setMatrId(matrFind.getId()).setMatrBaseTypeForImport(matrFind.getBaseType());
            stock.setFlagOmoc(matrFind.getFlagOmoc()).setFlagConsignment(matrFind.getFlagConsignment());
            if (StringUtils.isBlank(stock.getMatrBaseTypeForImport())) {
                stock.setMatrBaseTypeForImport("matr");
            }

            stock.setAmount(stock.getSkuQty() * stock.getSkuPrice());

            unitFindKey = stock.getMatrId() + stock.getSkuUnit();
            if (!matrUnitMapByMatrIdAndUnit.containsKey(unitFindKey)) {
                BusinessException.throwValidFail("第%s行,单品单位未找到",lineIndex);
            }

            if (StringUtils.isNotBlank(stock.getMfgName())) {
                mfgFind = mfgByName.get(stock.getMfgName());
                if (mfgFind == null) {
                    mfgFind = new Mfg();
                    mfgFind.setName(stock.getMfgName());
                    mfgFind.setNamePy(StringUtils.substring(PinYinUtils.getAlpha(mfgFind.getName()),0,10));
                    mfgFind.setHrpMfg(mfgFind.getName());
                    mfgFind.setId(IdWorker.getIdStr());
                    mfgMapper.insert(mfgFind);
                    mfgByName.put(stock.getMfgName(), mfgFind);
                }
            }
        }

    }
    // 根据导入库存产生入库明细
    @Override
    public String createByStockImport(List<Stock> stockList) {
        fillStockInfo(stockList);

        // 根据商品基础分类、入库仓库、供应商分组
        Map<String,List<Stock>> inGroup = stockList.stream().collect(Collectors.groupingBy(
                t ->
                        t.getMatrBaseTypeForImport() + t.getWarehouseId() + t.getSupplierId() + t.getFlagOmoc() + t.getFlagConsignment()
                )
        );
        Stock stockTop1;
        WorkOrder inWorkOrder;
        String loginUserName = UserUtils.currentUser().getName();
        Date dateNow = DateUtils.now();
        Date expDateDefault = DateUtils.parse("2099-01-01");
        LocalDateTime localDateTime = LocalDateTime.now();

        WorkOrderItem itemIn;
        //        仓库默认库位
        Location defaultLocation;


        List<WorkOrderItem> saveItem = new ArrayList<>();
        List<WorkOrder> inList = new ArrayList<>();
        String unitFindKey;
        String remark = StrUtil.format(
                "库存导入，时间:{},操作人:{}",
                DateUtils.format(DateUtils.nowDate(DateUtils.YYYYMMDDHHMMSS_PATTER2),DateUtils.YYYYMMDDHHMMSS_PATTER2),
                UserUtils.currentUser().getName()
        );

        for(List<Stock> stockListGroup : inGroup.values()) {
            stockTop1 = stockListGroup.get(0);
            defaultLocation = locationService.getDefaultLocation(stockTop1.getWarehouseId());
            inWorkOrder = new WorkOrder();
            inWorkOrder.setFlowStatus(GlobalConsts.FLOW_END_VALUE); //已审核
            inWorkOrder.setBusUser(loginUserName).setBusDate(dateNow);
            inWorkOrder.setDeptId(UserUtils.currentUser().getDeptId()).setDeptName(UserUtils.currentUser().getDeptName());
            inWorkOrder.setBusType("IN_MANUAL");
            inWorkOrder.setDirection(GlobalConsts.ORDER_DIRECTION_IN)
                    .setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.IN_ORDER_BUS_KEY))
                    .setWarehouseId(stockTop1.getWarehouseId())
                    .setWarehouseName(stockTop1.getWarehouseName())
                    .setFlowModifier(loginUserName)
                    .setFlowModified(localDateTime)
            ;
            inWorkOrder.setId(IdWorker.getIdStr());
            inWorkOrder.setPurchaseOrderType(stockTop1.getMatrBaseTypeForImport());
            inWorkOrder.setSupplierId(stockTop1.getSupplierId()).setSupplierName(stockTop1.getSupplierName());
            inWorkOrder.setFlagOmoc(stockTop1.getFlagOmoc()).setFlagConsignment(stockTop1.getFlagConsignment());
            inWorkOrder.setRemark(remark);
            inWorkOrder.setGmtCreate(localDateTime).setCreator(loginUserName);
            inWorkOrder.setAmount(stockListGroup.stream().mapToDouble(Stock::getAmount).sum());
            inList.add(inWorkOrder);

            for(Stock stock : stockListGroup) {
                itemIn = new WorkOrderItem();
                BeanUtils.copyProperties(stock, itemIn);
                itemIn.setLocationId(defaultLocation.getId()).setLocationName(defaultLocation.getName());
                itemIn.setWorkOrderId(inWorkOrder.getId());
                itemIn.setId(IdWorker.getIdStr());
                itemIn.setLineId(itemIn.getId());
                itemIn.setPackageUnit(itemIn.getSkuUnit()).setPackageRate(1d).setPackageQty(itemIn.getSkuQty());
                if (StringUtils.isBlank(itemIn.getLot())) {
                    itemIn.setLot("无");
                }
                if (itemIn.getExpDate() == null) {
                    itemIn.setExpDate(expDateDefault);
                }

                saveItem.add(itemIn);
            }
        }

        this.saveBatch(inList);
        workOrderItemService.saveBatch(saveItem);

        workOrderService.postBatch(inList.stream().map(WorkOrder::getId).collect(Collectors.toList()));


        return StrUtil.format("导入成功，新增入库单:{}",inList.size());
    }

}
